iT邦幫忙

2022 iThome 鐵人賽

DAY 25
0

今天要來看看初始化了。也是很長一大篇。

初始化

初始化就是使用 Class, Struct, enum 類型實例之前的準備過程。在新的實例使用前有個過程是必須的,它包括設置實例中存儲屬性的初始值跟姪習其他必須的設置或初始化。

存儲屬性的初始賦值

在 Class 和 Struct 實例化石,必須為所有存儲屬性設置合適的初始值。存儲屬性不能是一個未知的狀態。可以在初始化器中為存儲屬性設置初始值,也可以在定義屬性時給予默認值。

初始化器

初始化器在創建某個類型的新實例時被調用。最簡單的形式為下面。

init() {

}

那我們來看一下官方的例子

struct Fahrenheit {
    var temperature: Double
    init() {
        temperature = 32.0
    }
}
var f = Fahrenheit()
print("The default temperature is \(f.temperature)° Fahrenheit")
// 打印“The default temperature is 32.0° Fahrenheit”

在初始化器裡面已經定義了 temperature 的數值為 32 所以被調用出來就會是 init 裡面的初始化數值。

默認屬性值

你也可以不在初始化器中給數值,也可以在屬性定義的值後給默認值

struct Fahrenheit {
    var temperature = 32.0
}

自定義初始化器

初始化器的參數

可以給參數到初始化器裡面。那我們看一下官方的例子。

struct Celsius {
    var temperatureInCelsius: Double
    init(fromFahrenheit fahrenheit: Double) {
        temperatureInCelsius = (fahrenheit - 32.0) / 1.8
    }
    init(fromKelvin kelvin: Double) {
        temperatureInCelsius = kelvin - 273.15
    }
}

let boilingPointOfWater = Celsius(fromFahrenheit: 212.0)
// boilingPointOfWater.temperatureInCelsius 是 100.0
let freezingPointOfWater = Celsius(fromKelvin: 273.15)
// freezingPointOfWater.temperatureInCelsius 是 0.0

這邊有兩個初始化器,裡面帶的參數個別是 標籤 fromFahrenheit 的 fahrenheit 跟標籤 fromKelvin 的 kelvin 。他們最後都會存到 temperatureInCelsius 裡面。

參數名稱及參數標籤

跟函數那邊的參數狀況一樣,然而初始化器並不像函數和方法那樣可以括號前有一個辨別的方法名。因此在調用初始化器的時候,主要通過初始化器參數命名和類型來確定要被調用的初始化器。
我們來看一下官方的例子

struct Color {
    let red, green, blue: Double
    init(red: Double, green: Double, blue: Double) {
        self.red   = red
        self.green = green
        self.blue  = blue
    }
    init(white: Double) {
        red   = white
        green = white
        blue  = white
    }
}

let magenta = Color(red: 1.0, green: 0.0, blue: 1.0)
let halfGray = Color(white: 0.5)

無實際參數標籤的初始化器參數

如果你不希望初始化器的某個參數使用參數標籤,可以寫一個 _ 來替代明確的實際參數標籤,以重寫默認行為。
那我們看一下官方的例子

struct Celsius {
    var temperatureInCelsius: Double
    init(fromFahrenheit fahrenheit: Double) {
        temperatureInCelsius = (fahrenheit - 32.0) / 1.8
    }
    init(fromKelvin kelvin: Double) {
        temperatureInCelsius = kelvin - 273.15
    }
    init(_ celsius: Double){
        temperatureInCelsius = celsius
    }
}

let bodyTemperature = Celsius(37.0)
// bodyTemperature.temperatureInCelsius 為 37.0

他延續了前面的例子,然後在新增一個初始化器,初始化器調用 Celsius(37.0) 不需要參數標籤,因此直接調用 init(_ celsius: Double) 這個初始化器。

可選屬性類型

如果 Class 裡命有一個允許值為 nil 的存儲行屬性,也許是他的值不能在初始化過程設置,或者他後面會是 nil 的屬性,所以宣告他為 可選類型。
那我們看一下官方的例子

class SurveyQuestion {
    var text: String
    var response: String?
    init(text: String) {
        self.text = text
    }
    func ask() {
        print(text)
    }
}

let cheeseQuestion = SurveyQuestion(text: "Do you like cheese?")
cheeseQuestion.ask()
// 打印“Do you like cheese?”
cheeseQuestion.response = "Yes, I do like cheese."

調查問題的答案在詢問前都是不能確認的,因此 response 就會是 String? 可選類型。

初始化中常量的賦值

你可以在任何時間給常量賦值,只要在初始化結束時有確定的數值。

看官方的例子

class SurveyQuestion {
    let text: String
    var response: String?
    init(text: String) {
        self.text = text
    }
    func ask() {
        print(text)
    }
}
let beetsQuestion = SurveyQuestion(text: "How about beets?")
beetsQuestion.ask()
// 打印“How about beets?”
beetsQuestion.response = "I also like beets. (But not with cheese.)"

默認初始化器

如果 Class 或 Struct 已經有提供默認值了,又沒有其他的自定義初始化器,那麼 Swift 本身會提供一個默認的初始化器。
看官方的例子

class ShoppingListItem {
    var name: String?
    var quantity = 1
    var purchased = false
}
var item = ShoppingListItem()
item.quantity
// 1
item.purchased
// false

結構體類型的成員初始化器

如果 Struct 沒有定義任何他的初始化器,那他會直接自動接收他的成員初始化器。跟默認初始化器不同的是即使沒有默認值,有可以拿到成員初始化器。

我們看下面的例子

struct Size {
    var width = 0.0, height = 0.0
}
let twoByTwo = Size(width: 2.0, height: 2.0)

調用的時候要給他數值。即時你不給數值他會自己給默認的數值。

let zeroByTwo = Size(height: 2.0)
print(zeroByTwo.width, zeroByTwo.height)
// 打印 "0.0 2.0"

let zeroByZero = Size()
print(zeroByZero.width, zeroByZero.height)
// 打印 "0.0 0.0"

好今天就先到這裡了。


上一篇
30天的 iOS 修仙道路 (24)
下一篇
30天的 iOS 修仙道路 (26)
系列文
30天的 iOS 修仙道路 站穩腳步基礎篇30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言